home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / simula / books / books.lha / kirkerud / postoffice.sim < prev    next >
Text File  |  1993-08-16  |  8KB  |  234 lines

  1. % ****************************************************************
  2. % *                                                              *
  3. % *  This is  the program constructed in section 14.8 of         *
  4. % *  Object Oriented Programming with Simula by Bj|rn Kirkerud;  *
  5. % *                                                              *
  6. % ****************************************************************
  7.  
  8.  
  9. external class settools;
  10.  
  11. settools begin
  12.  
  13.   element class customer(arrival_time);  real arrival_time;
  14.     begin
  15.  
  16.       real  length_of_service, start_of_service_time;
  17.  
  18.       Boolean procedure will_join_queue(queue_length); integer queue_length;
  19.         will_join_queue := queue_length <= randint(0, 15, seed);
  20.  
  21.       procedure service_starts(time); real time;
  22.         start_of_service_time := time;
  23.  
  24.       Boolean procedure errand_done(time); real time;
  25.         errand_done := time ge start_of_service_time + length_of_service;
  26.  
  27.       real procedure wait_time;
  28.         wait_time := start_of_service_time - arrival_time;
  29.  
  30.       procedure display;
  31.         begin
  32.           outtext("Anonymous customer arrived at time ");
  33.             outfix(arrival_time, 1, 6);
  34.           outtext(",  with length of service-time ");
  35.             outfix(length_of_service, 1, 6);  outtext(" seconds.");
  36.           outimage;
  37.         end;
  38.  
  39.       length_of_service := normal(105, 30, seed);
  40.  
  41.     end of customer;
  42.  
  43.  
  44.   class counter(counter_number); integer counter_number;
  45.     begin
  46.  
  47.       ref(customer) current_customer;
  48.       ref(sequence) the_queue;
  49.  
  50.       integer total_number_of_customers,
  51.                 max_queue_length;
  52.       real    sum_idle_time,
  53.                 start_idle_time,  
  54.                 sum_service_time,
  55.                 sum_wait_time;
  56.  
  57.       procedure arrive(a_customer);  ref(customer) a_customer;
  58.         if current_customer == none
  59.           then begin
  60.               current_customer :- a_customer;
  61.               a_customer.service_starts(a_customer.arrival_time);
  62.               sum_idle_time := sum_idle_time + 
  63.                                a_customer.arrival_time - start_idle_time;
  64.             end
  65.           else begin
  66.               the_queue.append(a_customer);
  67.               max_queue_length := max(max_queue_length, the_queue.size);
  68.             end;
  69.  
  70.       integer procedure number_of_customers;
  71.         number_of_customers := if current_customer == none then 0
  72.                        else 1 + the_queue.size;
  73.  
  74.       procedure check_current_customer(time); real time;
  75.         if current_customer =/= none and then current_customer.errand_done(time)
  76.         then current_customer_leaves;
  77.  
  78.       procedure current_customer_leaves;
  79.         begin real time;
  80.           time := current_customer.start_of_service_time +
  81.                 current_customer.length_of_service;
  82.           sum_service_time := sum_service_time +  
  83.                               current_customer.length_of_service;
  84.           sum_wait_time    := sum_wait_time + current_customer.wait_time;
  85.           total_number_of_customers := total_number_of_customers + 1;
  86.           if the_queue.is_empty
  87.             then begin current_customer :- none;  start_idle_time := time end
  88.             else begin
  89.               current_customer :- the_queue.head;
  90.               current_customer.service_starts(time);
  91.               the_queue :- the_queue.tail;
  92.             end;
  93.         end;
  94.  
  95.       procedure day_is_over;
  96.         while current_customer =/= none do current_customer_leaves;
  97.  
  98.       procedure write_statistics;
  99.         begin
  100.           outint(counter_number, 4);
  101.           outint(total_number_of_customers, 11);
  102.           outfix(sum_service_time, 1, 13);
  103.           outfix(sum_idle_time, 1, 9);
  104.           outint(max_queue_length, 6);
  105.           outimage;
  106.         end;
  107.  
  108.       procedure display;
  109.         begin
  110.           outtext("Counter "); outint(counter_number, 0);
  111.           if current_customer =/= none then
  112.             begin
  113.               outtext(" is currently serving ");   current_customer.display;
  114.               if the_queue.is_empty then  User_message( "Empty queue.")
  115.               else begin
  116.                 User_message( "A queue with the following  customers:");
  117.                 the_queue.display;
  118.               end;
  119.             end
  120.           else User_message(" is currently serving no  customer");
  121.         end;
  122.  
  123.     !   Initialization: ;
  124.  
  125.       the_queue :- new sequence;
  126.  
  127.     end of counter;
  128.  
  129.  
  130.   class post_office(number_of_counters);  integer number_of_counters;
  131.     begin
  132.  
  133.       ref(counter) array  the_counters(1 : number_of_counters);
  134.  
  135.       integer customers_lost;
  136.  
  137.       procedure arrive(a_customer);  ref(customer) a_customer;
  138.         begin  
  139.           integer counter_number, min_queue_length, counter_with_min_queue;
  140.           min_queue_length := maxint;
  141.           for counter_number := 1 step 1 until number_of_counters do
  142.             begin
  143.               the_counters(counter_number).
  144.                    check_current_customer( a_customer.arrival_time);
  145.               if the_counters(counter_number).
  146.                    number_of_customers < min_queue_length then
  147.                 begin
  148.                   min_queue_length := the_counters(counter_number).
  149.                                           number_of_customers;
  150.                   counter_with_min_queue := counter_number;
  151.                 end;
  152.             end;
  153.           if a_customer.will_join_queue(min_queue_length)
  154.             then the_counters(counter_with_min_queue).arrive(a_customer)
  155.             else customers_lost := customers_lost + 1;
  156.         end of arrive;
  157.  
  158.       procedure day_is_over;
  159.         begin integer counter_number;
  160.           for counter_number := 1 step 1 until  number_of_counters do
  161.             the_counters(counter_number).day_is_over;
  162.         end;
  163.  
  164.       procedure write_statistics;
  165.         begin
  166.           real sum_service_time, sum_wait_time;
  167.           integer total_number_of_customers, counter_number;
  168.           User_message("Counter   Number of   Service    Idle    Max");
  169.           User_message("number    customers     time     time   queue");
  170.           for counter_number := 1 step 1 until  number_of_counters do
  171.             begin
  172.               the_counters(counter_number).write_statistics;
  173.               sum_service_time := sum_service_time +
  174.                      the_counters(counter_number) .sum_service_time;
  175.               sum_wait_time := sum_wait_time +
  176.                      the_counters(counter_number).sum_wait_time;
  177.               total_number_of_customers :=  total_number_of_customers +
  178.                      the_counters(counter_number) .total_number_of_customers;
  179.             end;
  180.           outtext("Total number of customers served: ");
  181.             outint(total_number_of_customers, 0); outimage;
  182.           outtext("Number of customers lost: ");
  183.             outint(customers_lost, 0);  outimage;
  184.           outtext("Total service time: ");
  185.             outint(sum_service_time, 0); outtext(" seconds"); outimage;
  186.           outtext("Average wait time: ");
  187.             outint(sum_wait_time/total_number_of_customers, 0);  
  188.             outtext(" seconds"); outimage;
  189.         end;
  190.  
  191.       procedure display;
  192.         begin integer counter_number;
  193.           User_message("Post office status:");
  194.           for counter_number := 1 step 1 until  number_of_counters do
  195.             the_counters(counter_number).display;
  196.         end;
  197.  
  198.     !  Initialize the counters:   ;
  199.       begin integer counter_number;
  200.         for counter_number := 1 step 1 until  number_of_counters do
  201.           the_counters(counter_number) :- new  counter(counter_number);
  202.       end;
  203.  
  204.     end of post_office;
  205.  
  206.  
  207.   procedure User_message(message); text message;
  208.     begin outtext(message); outimage end;
  209.  
  210.   integer number_of_counters;
  211.  
  212.   integer seed;
  213.  
  214.   seed := 123795;
  215.  
  216.   for number_of_counters := 1, 2, 3, 4, 5 do
  217.   begin
  218.     inspect new post_office(number_of_counters) do
  219.       begin
  220.         inspect new infile("poff.dta") do
  221.           begin
  222.             open(blanks(80));
  223.             while not lastitem do
  224.               arrive(new customer(inreal));
  225.             close;
  226.           end;
  227.         day_is_over;
  228.         write_statistics; outimage;
  229.       end;
  230.   end;
  231.  
  232. end of program;
  233.  
  234.